package com.handpay.framework.swiper;

import android.content.Context;

import com.handpay.framework.swiper.ic.IICSelectApplicationCallback;
import com.handpay.framework.swiper.ic.IShowSelectApplication;
import com.handpay.framework.utils.CommonUtils;
import com.handpay.zztong.hp.config.ZZTConstant;
import com.handpay.zztong.hp.log.HPLog;
import com.mset.cardswiper.CMsetSwiper;
import com.mset.cardswiper.CSwiperStateListener;
import com.mset.cardswiper.Convert;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Locale;
import java.util.concurrent.TimeoutException;

/**
 * 酷漫刷卡器的封装
 * 
 * @author zzmiao
 * 
 */
public class CMSETSwiper extends AbstractBbposSwiper implements CSwiperStateListener {
	private static final String TAG = "CMSETSwiper";
	private Context context;
	protected AsynSwiperLock mLock;
	protected IShowSelectApplication mSelectApplication;
	private CMsetSwiper cmsetswiper = null;
	public boolean isSwiperOk = false;
	private String strCSN = null;
	private String curTimeStr = null;
	private static String macStr = null;
	private boolean isStop = true; 
	private Hashtable<String, String> mHTData = new Hashtable<String, String>();
	private String mData;
	public CMSETSwiper(Context context, IShowSelectApplication selectApplication) {
		HPLog.e(TAG, ">>>>CMSETSwiper<<<<");
		this.context = context;
		mSelectApplication = selectApplication;
		isSwiperOk = true;
		mLock = new AsynSwiperLock();
		initSdk();
	}

	private void initSdk() {
		HPLog.e(TAG, ">>>>CMSETSwiper:initSdk<<<<");
		try {
			if (cmsetswiper == null) {
				cmsetswiper = new CMsetSwiper(context, this);
				cmsetswiper.connectCSwiper();
			}
		} catch (Exception e) {
			HPLog.e(TAG, ">>>>CMSETSwiper:initSdk :Exception<<<<");
			e.printStackTrace();
		}
	}

	@Override
	public String getCSN() {
		HPLog.e(TAG, ">>>>getCSN<<<<");
		strCSN = null;
		cmsetswiper.getCSN();
		try {
			mLock.lock(ZZTConstant.SWIPER_TIMEOUT, AsynSwiperLock.GETCSN);
		} catch (TimeoutException te) {
			HPLog.i(TAG, "getCSN Exption", te);
		}
		HPLog.e(TAG, ">>>>getCSN strCSN:<<<<"+strCSN);
		return strCSN == null ? null : strCSN.toUpperCase(Locale.US);
	}

	@Override
	public boolean stopOperation() {
		HPLog.e(TAG, ">>>>stopOperation<<<<");
		// cmsetswiper.stopCSwiper();
		isStop = false;
		mData = null;
		mHTData.clear();
		mLock.unlock(AsynSwiperLock.IDLE);
		if(cmsetswiper != null){
			cmsetswiper.stopCSwiper();
		}
		return true;
	}

	@Override
	public boolean closeDevice() {
		HPLog.e(TAG, ">>>>closeDevice<<<<");
		stopOperation();
		isSwiperOk = false;
		context = null;
		mSelectApplication = null;
		if(cmsetswiper != null){
			cmsetswiper.releaseCSwiper();
			cmsetswiper = null;
		}
		return true;
	}

	@Override
	public SwipeResult swipeCard(String factor, int timeout) {
		if (cmsetswiper == null) {
			return new SwipeResult(SwipeStatus.SWIPE_ERROR);
		}
		HPLog.e(TAG, ">>>>swipeCard<<<<");
		HPLog.e(TAG, factor);
		isStop = true;
		// SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss");
		// Date curDate = new Date(System.currentTimeMillis());// 获取当前时间
		curTimeStr = factor.substring(0, factor.length() - 2);
		HashMap<String, String> keyData = new HashMap<String, String>();
		keyData.put("transaction_submitTime", curTimeStr);
		keyData.put("transaction_type", "Purchase.APReq");
		cmsetswiper.startCSwiper(keyData);
		try {
			mLock.lock(timeout, AsynSwiperLock.NEW_SWIPE_CARD);
		} catch (TimeoutException te) {
			HPLog.i(TAG, "", te);
			return new SwipeResult(SwipeStatus.SWIPE_TIMEOUT);
		}
		if (null != mHTData.get(IBusinessSwiper.BANK_PLAIN_ACCOUNT_KEY)) {
			SwipeResult result = new SwipeResult(SwipeStatus.SWIPE_OK,
					mHTData.get(IBusinessSwiper.BANK_PLAIN_ACCOUNT_KEY));
			if ("2".equals(mHTData.get("isICC"))) {
				result.mCardType = mHTData.get("cardType");
			}
			return result;
		}
		if(!isStop){
			HPLog.i(TAG, "--isStop--"+isStop);
			return new SwipeResult(SwipeStatus.SWIPE_CANCEL);
		}
		return new SwipeResult(SwipeStatus.SWIPE_ERROR);
	}

	@Override
	public String encData(String data, String index, String factor) {
		HPLog.e(TAG, "encData-data: " + data + " index: " + index);
		HPLog.e(TAG, factor);
		if (ISwiperListener.KeyDataIndex.equals(index)) {
			data= formatData(data, 0);
			HPLog.e(TAG, "encData-data-format"+data);
			cmsetswiper.encryptDataEx(data, factor, 13, 0);
			try {
				mLock.lock(ZZTConstant.SWIPER_TIMEOUT, AsynSwiperLock.CACL_DATA);
			} catch (TimeoutException te) {
				HPLog.i(TAG, "", te);
			}
			return mData;
		} else if (PIN_INDEX.equals(index)) {
			cmsetswiper.encryptDataEx(String.format("06%sFFFFFFFF", data),
					factor, 14, 0);
			try {
				mLock.lock(ZZTConstant.SWIPER_TIMEOUT, AsynSwiperLock.CACL_DATA);
			} catch (TimeoutException te) {
				HPLog.i(TAG, "", te);
			}
			return mData;
		} else if (ISwiperListener.MacDataIndex.equals(index)) {
			String macplain = null;
			ByteArrayOutputStream bos = new ByteArrayOutputStream();
			try {
				bos.write(String.valueOf(data.toCharArray()).getBytes());
				bos.write(0x80);
				while (bos.size() % 8 != 0) {
					bos.write(0x00);
				}
				bos.write(0x80);
				for (int i = 0; i < 7; i++) {
					bos.write(0x00);
				}
				byte[] macPlainBytes = bos.toByteArray();
				macplain = CommonUtils.bytesToHexString(macPlainBytes);
			} catch (IOException ioe) {
				HPLog.e(TAG, "", ioe);
				try {
					bos.close();
				} catch (IOException e) {
					HPLog.e(TAG, "", e);
				}
			}
			HPLog.e(TAG, "加密前Mac:" + macplain);
			cmsetswiper.getMAC(macplain, factor);
			try {
				mLock.lock(ZZTConstant.SWIPER_TIMEOUT, AsynSwiperLock.CACL_MAC);
			} catch (TimeoutException te) {
				HPLog.i(TAG, "", te);
			}
			return macStr;
		}
		return null;
	}

	@Override
	public Hashtable<String, String> batchEncData(
			Hashtable<Integer, String> htDatas, String factor) {
		return null;
	}


	@SuppressWarnings("unchecked")
	@Override
	public Hashtable<String, String> getBankInfo() {
		Hashtable<String, String> result = (Hashtable<String, String>) mHTData
				.clone();
		mHTData.clear();
		return result;
	}

	@Override
	public boolean isSwiperReady() {
		HPLog.i(TAG, ">>>>isSwiperReady<<<<"+isSwiperOk);
		return isSwiperOk;
	}

	@Override
	public SwiperModel getSwiperModel() {
		HPLog.i(TAG, ">>>>getSwiperModel<<<<");
		return SwiperModel.CMSET_VOICE;
	}

//	@Override
//	public Result affirmAmount(String amount, int timeout) {
//		HPLog.i(TAG, ">>>>affirmAmount<<<<");
//		return Result.OK;
//	}

//	@Override
//	public Result inputPwd(String factor, int timeout) {
//		HPLog.e(TAG, ">>>>inputPwd<<<<");
//		return Result.OK;
//	}

//	@Override
//	public SwipeResult registerPwd(String factor, int timeout) {
//		return null;
//	}

	private String mPwdString;

//	@Override
//	public void setPlainPwd(String pwd) {
//		mPwdString = pwd;
//	}

	@Override
	public void onDecodeCompleted(String CSN,
			HashMap<String, String> transData, boolean isICC) {
		HPLog.i(TAG, transData.toString());
		if (isICC) { // IC卡
			mHTData.put(IBusinessSwiper.BANK_PLAIN_ACCOUNT_KEY,
					transData.get("pan"));
			mHTData.put(IBusinessSwiper.BANK_DCDATA,
					transData.get("transaction_DCData"));
			mHTData.put(
					IBusinessSwiper.BANK_DYNAMIC_KEY,
					transData.get("transaction_dynamicKeyData").toUpperCase(
							Locale.US));
			mHTData.put(
					IBusinessSwiper.BANK_TRACK2_KEY,
					BusinessSwiper.autoFillTrack2(transData.get(
							"transaction_track2Data").toUpperCase(Locale.US)));
			mHTData.put(IBusinessSwiper.BANK_ICNUMBER,
					transData.get("transaction_ICNumber"));
			//expireDate=3010, 
			//transaction_expireDate=30648F3DA45033D2, 
			mHTData.put("isICC", "1");
			//新版 2.0.0   添加ＩＣ卡有效期
			String  expireDate= transData.get("expireDate");
			if (CommonUtils.checkExpireDate(expireDate)) {
				expireDate = expireDate.substring(0, 4);
				HPLog.i(HPLog.FDL_TAG, "CMSETSwiper  -- plainExpireDate:"+expireDate);
				mHTData.put(IBusinessSwiper.BANK_PLAIN_EXPIRE_DATE, expireDate);
			} else {
				HPLog.i(TAG, "CMSETSwiper IC card but no plainExpireDate");
			}
		} else { // 磁条卡
			mHTData.put(IBusinessSwiper.BANK_PLAIN_ACCOUNT_KEY,
					transData.get("pan"));
			mHTData.put(
					IBusinessSwiper.BANK_DYNAMIC_KEY,
					transData.get("transaction_dynamicKeyData").toUpperCase(
							Locale.US));
			mHTData.put(
					IBusinessSwiper.BANK_TRACK2_KEY,
					BusinessSwiper.autoFillTrack2(transData.get(
							"transaction_track2Data").toUpperCase(Locale.US)));
			mHTData.put("cardType", transData.get("serviceCode")
					.substring(0, 1));
			mHTData.put("isICC", "2");
			
			//新版 2.0.0   添加ＩＣ卡有效期
			String  expireDate= transData.get("expireDate");
			if (CommonUtils.checkExpireDate(expireDate)) {
				expireDate = expireDate.substring(0, 4);
				HPLog.i(HPLog.FDL_TAG, "CMSETSwiper  -- plainExpireDate:"+expireDate);
				mHTData.put(IBusinessSwiper.BANK_PLAIN_EXPIRE_DATE, expireDate);
			} else {
				HPLog.i(TAG, "CMSETSwiper IC card but no plainExpireDate");
			}
		}
		mLock.unlock(AsynSwiperLock.NEW_SWIPE_CARD);
	}

	@Override
	public void onDecodeError() {
		HPLog.i(TAG, ">>>>onDecodeError<<<<");
		mHTData.clear();
		mLock.unlock(AsynSwiperLock.NEW_SWIPE_CARD);
	}

	@Override
	public void onDetectIcc() {
		HPLog.i(TAG, "检测到IC卡插入,正在读取IC卡数据...");
	}

	@Override
	public void onDetectIcc(ArrayList<String> appLabel) {
		HPLog.i(TAG, "检测到多应用IC卡插入,正在读取IC卡数据...");
		// 检测到多应用卡 选择多目录应用后进行IC卡交易
		mSelectApplication.showSelectICApp(appLabel,
				new IICSelectApplicationCallback() {
					@Override
					public void onCardTypeSelect(int index) {
						cmsetswiper.startICCTrans(index);
					}
				});
	}

	@Override
	public void onDetectInvalidCard() {
		HPLog.i(TAG, ">>>>onDetectInvalidCard<<<<");
		mHTData.clear();
		mLock.unlock(AsynSwiperLock.IDLE);
	}

	@Override
	public void onDevicePlugged() {
		HPLog.i(TAG, ">>>>onDevicePlugged<<<<");
	}

	@Override
	public void onDeviceUnplugged() {
		HPLog.i(TAG, ">>>>onDeviceUnplugged<<<<");
	}

	@Override
	public void onError(int arg0, String arg1) {
		HPLog.i(TAG, ">>>>onError<<<<int arg0, String arg1 =" + arg1);
		mData = null;
		mHTData.clear();
		mLock.unlock(AsynSwiperLock.IDLE);
	}

	@Override
	public void onGetBalanceComplete(String arg0, String arg1) {
		HPLog.i(TAG, ">>>>onGetBalanceComplete<<<<");
	}

	@Override
	public void onGetCSNCompleted(String CSN) {
		HPLog.i(TAG, "onGetCSNCompleted: " + CSN);
		strCSN = CSN;
		mLock.unlock(AsynSwiperLock.GETCSN);
	}

	@Override
	public void onICResponse(int arg0, byte[] arg1, byte[] arg2) {
		HPLog.i(TAG, ">>>>onICResponse<<<<");
	}

	@Override
	public void onNoDeviceDetected() {
		HPLog.i(TAG, ">>>>onNoDeviceDetected<<<<");
	}

	@Override
	public void onWaitSwipeTimeout() {
		HPLog.i(TAG, ">>>>onWaitSwipeTimeout<<<<");
	}

	@Override
	public void onWaitingForCardSwipe() {
		HPLog.e(TAG, ">>>>onWaitingForCardSwipe<<<<");
	}

	@Override
	public void onWaitingForCryptoData() {
		HPLog.i(TAG, ">>>>onWaitingForCryptoData<<<<");
	}

	@Override
	public void onWaitingForDevice() {
		HPLog.e(TAG, ">>>>onWaitingForDevice<<<<");
	}

	@Override
	public void onWaitingForICCard() {
		HPLog.e(TAG, ">>>>onWaitingForICCard<<<<");
	}

	@Override
	public void onEncryptedComleted(String arg0, HashMap<String, String> arg1) {
		HPLog.i(TAG, ">>>>onEncryptedComleted<<<<");
	}

	@Override
	public void onGetEncDataComplete(String result) {
		HPLog.i(TAG, "result: " + result);
		mData = result;
		mLock.unlock(AsynSwiperLock.CACL_DATA);
	}

	@Override
	public void onGetMACComplete(String mac) {
		HPLog.i(TAG, "mac: " + mac);
		macStr = mac;
		mLock.unlock(AsynSwiperLock.CACL_MAC);
	}

	@Override
	public void onGetPanComplete(String arg0, String arg1, String arg2,
			boolean arg3) {
		HPLog.i(TAG, ">>>>onGetPanComplete<<<<");
	}

	@Override
	public void onGetTransLogComplete(String arg0, int arg1, String arg2) {
		HPLog.i(TAG, ">>>>onGetTransLogComplete<<<<");
	}



	@Override
	public void onDeviceLowPower(String arg0) {
		// 刷卡器电量低于30时提示
		HPLog.e(TAG, ">>>>onDeviceLowPower : battery<<<<" + arg0);
		if (null != mSelectApplication
				&& mSelectApplication instanceof SwiperCallback) {
			((SwiperCallback) mSelectApplication).onBatteryLow();
		}
	}
	 //格式化数据  type=0:关键数据   type=1 mac数据
    public String formatData(String data ,int type)
    {
    	int len;
    	String outString = null;
    	StringBuffer sb = new StringBuffer();
    	if(mSwiperMode == SwiperMode.SUPER_TRANS){
    		HPLog.e("fyang", "super");
    		sb.append( Convert.bytesToHexString(data.getBytes()));
    	}else {
    		HPLog.e("fyang", "normal");
    		sb.append( Convert.bytesToHexString(CommonUtils.hexStringToBytes(data)));
		}
    	
    	
    	if(type == 0){
    		len =sb.length();
    		while((len % 16) > 0){
    			sb.append("00");
    			len =sb.length();
    		}
    	}else if(type == 1){ //mac
    		sb.append("80");
    		len =sb.length();
    		while((len % 16) > 0){
    			sb.append("00");
    			len =sb.length();
    		}
    		sb.append("8000000000000000");    	
    	}
    	
    	return sb.toString();
    }
}
